iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 27
0

成品連結:Click and Drag操作前程式碼完成後程式碼

今天要做的是拖拉的功能。從成品可以看到當按下滑鼠拖拉時元素的 X 軸會被拉著滾動,其實在實作後發現並不難,反而是覺得做處扇子狀的 CSS 很厲害啊...希望大家也可以花一些時間看一下 CSS 是怎麼寫的;作者用了許多我認為新奇且厲害的方法,像是呈現出立體視角的 perspective

操作步驟

首先要先分析需要什麼監聽事件以及要做什麼事

  • 按下滑鼠時:在 div.items 加入 class active
  • 鬆開滑鼠或移出 div.items:移除 class active
  • 按下滑鼠 + 移動:拖曳 div.items 的 X 軸

設定監聽事件

從待辦事項可以看出我們需要要事件分別是

  • mousedown
  • mouseupmouseleave
  • mousedownmousemove

那就先設定監聽吧!

const items = document.querySelector('.items');

items.addEventListener('mousedown', focus);
items.addEventListener('mousemove', drag);
items.addEventListener('mouseup', unfocus);
items.addEventListener('mouseleave', unfocus);

設定 isDown flag

flag 意思是旗幟,也就是用於標示是否已按下滑鼠,若 isDown === true 則執行 mousedown 的 callback focus,反之若 isDown === false 則執行 callback unfocus。預設是 false,當按下滑鼠時才會變成 true

let isDown = false;

function focus() {
    isDown = true;
    items.classList.add('active');  // 加入 class `active`
}

function unfocus() {
    isDown = false;
    items.classList.remove('active');  // 移除 class `active`
}

從上面程式碼可以看到當按下滑鼠時一併加入 class activeitems;當滑鼠移出 items 或鬆開滑鼠時移除該 class

設定拖曳

至於要拖曳就要先確保滑鼠已按下,這也是為何要設定 flag isDown 作為提示,而在 callback drag 中當 isDown !== true 時要立即退出 funciton 執行,反之才繼續執行

function drag(e) {
    if (!isDown) return;
    items.scrollLeft += -(e.movementX * 2);
}

如何拖曳?

這裡我觀察了一下 mousemoveevent 的屬性與方法(也就是在 dragconsole.log(e)),赫然發現有 MouseEvent.movementX 這個屬性。根據 MDN 所定義,這個屬性提供了拖曳起點到當前位置(X 軸)的距離,這正是我需要的!

另外看了一下 items 的屬性及方法(console.dir(items)),發現有個屬性 scrollLeft 正是用來設定(或顯示) X 滾軸當前位置。

綜合以上兩個資訊,我得知我將 MouseEvent.movementX 的值加到當前 X 滾軸位置就可以拖曳了!

function drag(e) {
    if (!isDown) return;
    // code here
}

至於為什麼要將 e.movementX * 2 設定正負相反是因為當向右拖曳時 e.movementX 會是負數,但我希望向右拖曳時可以向右滾動,所以將 e.movementX 的值正負相反過來

e.movementX * 2 則是因為我希望拖曳的距離可以拉長,所以乘以 2,如果你覺得不夠也可以乘以更大的數字。

總之今天的作品就完成了!

Reference


上一篇
JS30 Day 26 - Stripe Follow Along Nav
下一篇
JS30 Day 28 - Video Speed Controller
系列文
一起挑戰 JavaScript 30 吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言